package com.functest.orm

import com.functest.framework.BaseFunctionalTest
import org.testng.annotations.DataProvider
import com.functest.orm.TestData.Student_withLongId
import org.testng.annotations.Test

/**
 * Created with IntelliJ IDEA.
 * User: MalyutinAA
 * Date: 16.07.13
 * Time: 13:58
 * To change this template use File | Settings | File Templates.
 */
class BaseProviderUsingFiltersTest extends BaseFunctionalTest {
    Closure petrAsClosure = {String a = "P", String b = 'etr' -> a+b}

    List[] exeptionList = [
            ['id', null, IllegalArgumentException]
            ,['id', 'ASDF', MissingPropertyException]
            ,['age', 20 , NoSuchFieldException]
            ,[null, 'ASDF', NullPointerException]
    ]
    List[] eqPositive =  [
            ['id', 2, [2], ['Ivan']]
            ,['id', '2', [2], ['Ivan']]
            ,['firstName', petrAsClosure, [-1], ['Petr']]
            ,['lastName', 'Ivanov', [2], ['Ivan']]
    ]

    List[] eqNegative = [
            ['id', 10, null]
            ,['lastName', '%rov', null]
    ]

    List[] neqPositive = [
            ['id', 21474836475, [-1,0,2,3,4,5], ['Petr','Maria','Ivan','Sidor','Looser L.','Alexandr']]
            ,['id', '21474836475', [-1,0,2,3,4,5], ['Petr','Maria','Ivan','Sidor','Looser L.','Alexandr']]
            ,['firstName', 'Julia', [-1,0,2,3,4,5], ['Petr','Maria','Ivan','Sidor','Looser L.','Alexandr']]
            ,['firstName', petrAsClosure, [0,2,3,4,5,21474836475], ['Maria','Ivan','Sidor','Looser L.','Alexandr','Julia']]
    ]

    List[] neqNegative = [

    ]

    List[] gtPositive = [
            ['id', 3, [4,5,21474836475], ['Looser L.','Alexandr','Julia']]
            ,['id', '3', [4,5,21474836475], ['Looser L.','Alexandr','Julia']]
            ,['firstName', 'L', [-1,0,3,4], ['Petr','Maria','Sidor','Looser L.']]
            ,['firstName', 'Looser L.', [-1,0,3], ['Petr','Maria','Sidor']]
            ,['firstName', petrAsClosure, [3], ['Sidor']]
    ]

    List[] gtNegative = [
            ['firstName', 'Z', null]
    ]

    List[] gtePositive = [
            ['id', 4, [4,5,21474836475], ['Looser L.','Alexandr','Julia']]
            ,['id', '4', [4,5,21474836475], ['Looser L.','Alexandr','Julia']]
            ,['firstName', 'L', [-1,0,3,4], ['Petr','Maria','Sidor','Looser L.']]
            ,['firstName', petrAsClosure, [-1,3], ['Petr','Sidor']]
            ,['firstName', 'Looser L.', [-1,0,3,4], ['Petr','Maria','Sidor', 'Looser L.']]
    ]

    List[] gteNegative = [
            ['firstName', 'Z', null]
    ]

    List[] ltPositive = [
            ['id', 1, [-1,0], ['Petr','Maria']]
            ,['id', '1', [-1,0], ['Petr','Maria']]
            ,['firstName', 'L', [2,5,21474836475], ['Ivan','Alexandr','Julia']]
            ,['firstName', petrAsClosure, [0,2,4,5,21474836475], ['Maria','Ivan','Looser L.','Alexandr','Julia']]
            ,['firstName', 'Looser L.', [2,5,21474836475], ['Ivan','Alexandr','Julia']]
    ]

    List[] ltNegative = [
            ['firstName', '1', null]
            ,['firstName', '', null]
            ,['lastName', 'A', null]
    ]

    List[] ltePositive = [
            ['id', 0, [-1,0], ['Petr','Maria']]
            ,['id', '0', [-1,0], ['Petr','Maria']]
            ,['firstName', 'L', [2,5,21474836475], ['Ivan','Alexandr','Julia']]
            ,['firstName', 'L%', [2,5,21474836475], ['Ivan','Alexandr','Julia']]
            ,['firstName', petrAsClosure, [-1,0,2,4,5,21474836475], ['Petr','Maria','Ivan','Looser L.','Alexandr','Julia']]
            ,['firstName', 'Looser L.', [2,4,5,21474836475], ['Ivan','Looser L.','Alexandr','Julia']]
    ]

    List[] lteNegative = [
            ['lastName', '', null]
    ]

    List[] inPositive = [
            ['id', [-10,'0',2,10], [0,2], ['Maria','Ivan']]
            ,['id', ['ФЫВА',2,'0',null], [0,2], ['Maria','Ivan']]
            ,['firstName', ['ФЫВА',2,'Ivan','Maria',petrAsClosure(),null], [-1,0,2], ['Petr','Maria','Ivan']]
            ,['lastName', ['Petrova','Ivanov',null,'Smirnov'], [0,2], ['Maria','Ivan']]
    ]

    List[] inNegative = [
            ['lastName', ['ФЫВА',2,'0',null], null]
            ,['lastName', ['%a',null], null]
            ,['id', null, IllegalArgumentException]
            ,['id', 'ASDF', IllegalArgumentException]
            ,['age', 20 , NoSuchFieldException]
            ,[null, 'ASDF', NullPointerException]
    ]

    List[] notInPositive = [
            ['id', [-1,0,'1',2,4,5], [3,21474836475], ['Sidor','Julia']]
            ,['id', [-1,0,'1',2,4,'Ivan'], [3,5,21474836475], ['Sidor','Alexandr','Julia']]
            ,['firstName', [1,0, petrAsClosure(),'Ivan','maria','Julia'], [0,3,4,5], ['Maria','Sidor','Looser L.','Alexandr']]
//            ,[ConditionOp.NOT_IN , 'id', [null,-1,0,'1',2,4,5], [3,21474836475], ['Sidor','Julia']]
//            ,[ConditionOp.NOT_IN , 'lastName', ['Petrov','Ivanov','Petrova','Sidorova'], [3,4,5], ['Sidor','Losser L.','Alexandr']]
//            ,[ConditionOp.NOT_IN , 'lastName', [null], [-1,0,2,3,4,5,21474836475], ['Petr','Maria','Ivan','Sidor','Losser L.','Alexandr','Julia']]
    ]

    List[] notInNegative = [
            ['id', [3,21474836475,-1,0,'1',2,4,5], null]
            ,['firstName', [1,2,'Petr','Ivan','Julia','Maria','Sidor','Looser L.','Alexandr'], null]
            ,['id', null, IllegalArgumentException]
            ,['id', 'ASDF', IllegalArgumentException]
            ,['age', 20 , NoSuchFieldException]
            ,[null, 'ASDF', NullPointerException]
    ]

    List[] likePositive = [
            ['id', '2', [2], ['Ivan']]
            ,['lastName', 'IVANOV', [2], ['Ivan']]
            ,['lastName', '%ROV', [-1,3], ['Petr', 'Sidor']]
            ,['firstName', petrAsClosure, [-1], ['Petr']]
    ]

    List[] likeNegative = [
            ['lastName', '%qw%', null]
    ]

    List[] notLikePositive = [
            ['id', '21474836475', [-1,0,2,3,4,5], ['Petr','Maria','Ivan','Sidor','Looser L.','Alexandr']]
            ,['firstName', '%R%', [2,21474836475], ['Ivan','Julia']]
            ,['firstName', petrAsClosure, [0,2,3,4,5,21474836475], ['Maria','Ivan','Sidor','Looser L.','Alexandr','Julia']]
    ]

    List[] notLikeNegative = [
            ['firstName', '%', null]
    ]

    List[] isNullPositive = [
            ['lastName', 'ФЫВА', [5], ['Alexandr']]
            ,['lastName', 909090, [5], ['Alexandr']]
            ,['lastName', null, [5], ['Alexandr']]
    ]

    List[] isNullNegative = [
            ['id','ФЫВА', null]
            ,[null, 'ASDF', NullPointerException]
            ,['age', 20, NoSuchFieldException]
    ]

    List[] isNotNullPositive = [
            ['lastName', 'ФЫВА', [-1,0,2,3,4,21474836475],['Petr','Maria','Ivan','Sidor','Looser L.','Julia']]
            ,['lastName', 909090, [-1,0,2,3,4,21474836475],['Petr','Maria','Ivan','Sidor','Looser L.','Julia']]
            ,['lastName', null, [-1,0,2,3,4,21474836475],['Petr','Maria','Ivan','Sidor','Looser L.','Julia']]
    ]

    List[] isNotNullNegative = [
            [null, 'ASDF', NullPointerException]
            ,['age', 20, NoSuchFieldException]
    ]
//
//    List allNegatives =  [
//            eqNegative,
//            neqNegative,
//            gtNegative,
//            gteNegative,
//            ltNegative,
//            lteNegative,
//            inNegative,
//            notInNegative,
//            likeNegative,
//            notLikeNegative,
//            isNullNegative,
//            isNotNullNegative,
//    ]
//
//    List allPositive = [
//            eqPositive,
//            neqPositive,
//            gtPositive,
//            gtePositive,
//            ltPositive,
//            ltePositive,
//            inPositive,
//            notInPositive,
//            likePositive,
//            notLikePositive,
//            isNullPositive,
//            isNotNullPositive
//    ]
//
//    List<String> opName = ['EQ','NEQ','GT','GTE','LT','LTE','IN','NOT_IN','LIKE','NOT_LIKE','IS_NULL', 'IS_NOT_NULL']


    //think about re-naming
     List[] setConditionOp( List[] testDataCase, ConditionOp operation){
          List returnedList = []
          testDataCase.each {returnedList.add(it.clone()) }
          returnedList.each { List eachList ->
              eachList.add(operation)
          }
     }
//
//    List[] eachList ( List[][] fullList, List<String> opName){
//        List[] bla
//        bla = opName.each {List e ->
//            e.add(setConditionOp(fullList.find {"${it}Negative"}, ConditionOp."$it"))
//        }
//    }

    @DataProvider(parallel = false )
    def Object [][] positiveWithSingleCondition(){

        Object [][] data =
             setConditionOp(eqPositive,ConditionOp.EQ) +
                    setConditionOp(neqPositive,ConditionOp.NEQ) +
                    setConditionOp(gtPositive,ConditionOp.GT) +
                    setConditionOp(gtePositive,ConditionOp.GTE)+
                    setConditionOp(ltPositive,ConditionOp.LT) +
                    setConditionOp(ltePositive,ConditionOp.LTE) +
                    setConditionOp(inPositive,ConditionOp.IN) +
                    setConditionOp(notInPositive,ConditionOp.NOT_IN) +
                    setConditionOp(likePositive,ConditionOp.LIKE) +
                    setConditionOp(notLikePositive,ConditionOp.NOT_LIKE) +
                    setConditionOp(isNullPositive,ConditionOp.IS_NULL) +
                    setConditionOp(isNotNullPositive,ConditionOp.IS_NOT_NULL)
        data
    }

    @DataProvider(parallel = false )
    def Object [][] negativeWithSingleCondition(){

        Object [][] data =
            setConditionOp(eqNegative,ConditionOp.EQ) +
                    setConditionOp(exeptionList, ConditionOp.EQ) +
                    setConditionOp(neqNegative, ConditionOp.NEQ) +
                    setConditionOp(exeptionList,ConditionOp.NEQ) +
                    setConditionOp(gtNegative, ConditionOp.GT) +
                    setConditionOp(exeptionList,ConditionOp.GT) +
                    setConditionOp(gteNegative, ConditionOp.GTE) +
                    setConditionOp(exeptionList, ConditionOp.GTE) +
                    setConditionOp(ltNegative, ConditionOp.LT) +
                    setConditionOp(exeptionList, ConditionOp.LT) +
                    setConditionOp(lteNegative, ConditionOp.LTE)+
                    setConditionOp(exeptionList, ConditionOp.LTE) +
                    setConditionOp(inNegative, ConditionOp.IN) +
                    setConditionOp(notInNegative, ConditionOp.NOT_IN) +
                    setConditionOp(likeNegative, ConditionOp.LIKE) +
                    setConditionOp(exeptionList , ConditionOp.LIKE) +
                    setConditionOp(notLikeNegative, ConditionOp.NOT_LIKE) +
                    setConditionOp(exeptionList, ConditionOp.NOT_LIKE) +
                    setConditionOp(isNullNegative, ConditionOp.IS_NULL) +
                    setConditionOp(isNotNullNegative,ConditionOp.IS_NOT_NULL)
//        add exceptions as separated test
        data
    }

    @Test(dataProvider = 'positiveWithSingleCondition')
    void usingFiltersPositiveTest(String field, def value, List id, List firstName, ConditionOp condition){
        asTest{
            List<Student_withLongId> students
            List<Condition> conditions = [Condition.of(field, condition, value)]
            students = Student_withLongId.provider.usingFilters(conditions)

            assert students.id == id
            assert students.firstName == firstName

        }
    }

    @Test(dataProvider = 'negativeWithSingleCondition')
    void usingFiltersNegativeTest(String field, def value, Class exeptionClass, ConditionOp condition){
        asTest{
            List<Student_withLongId> students
            List<Condition> conditions = [Condition.of(field, condition, value)]
            try{
                students = Student_withLongId.provider.usingFilters(conditions)
            }
            catch (Throwable e){
                assert e in exeptionClass
            }
            if(!Throwable) assert students == null
        }
    }

    @Test
    void positiveTestsWithSeveralConditions(){
        asTest{
            List<Student_withLongId> students

            asStep('test with single result'){
                List conditions = [Condition.of('id', ConditionOp.EQ, 2), Condition.of('lastName', ConditionOp.LT, 'Z')]
                students = Student_withLongId.provider.usingFilters(conditions)
                assert students.firstName == ['Ivan']
            }

            asStep('test with several results'){
                List conditions = [Condition.of('id', ConditionOp.GTE, 0), Condition.of('lastName', ConditionOp.LIKE, '%ova')]
                students = Student_withLongId.provider.usingFilters(conditions)
                assert students.firstName == ['Maria','Julia']
            }
        }
    }

    @Test
    void negativeTestsWithSeveralConditions(){
        asTest{
            List<Student_withLongId> students

            asStep('test without result'){
                List conditions = [Condition.of('id', ConditionOp.EQ, 5), Condition.of('firstName', ConditionOp.EQ, 'Ivan')]
                students = Student_withLongId.provider.usingFilters(conditions)
                assert students == []
            }
            asStep('test with null condition'){
                List conditions = [Condition.of('id', ConditionOp.EQ, 5), null]
                try{
                    students = Student_withLongId.provider.usingFilters(conditions)
                }
                catch (Throwable e)
                {
                     assert e in NullPointerException
                }
            }
        }
    }

}
